#include "Uart4Data.h"
#include "protol_machine.h"
#include "stdio.h"
#include "string.h"
#include "DeviceInfo.h"
#include "version.h"
#include "rng.h"

#include "DeviceInfoBLL.h"
#include "UpdateBLL.h"
#include "UpdateData.h"
#include "Tools.h"
#include "flash.h"
#include "xp_mem_pool.h"

static ProtolElement pe_header;
static ProtolElement pe_cmder;
static ProtolElement pe_packnum;
static ProtolElement pe_length;
static ProtolElement pe_data;
static ProtolElement pe_state;
static ProtolElement pe_crc;

static int LoginResponseCmdProc(void *content, int data_length);
static int UpdateResponseCmdProc(void *content, int data_length);

static ProtolMachine* init_uart4data_protolset(void)
{
	ProtolMachine *pm = NULL;
	bool protolInitRes = false;

	protolInitRes = InitProtolMachine(&pm);
	
	if(protolInitRes)
	{
		SetDataOnlyFlag(pm, FRAME_DATALENGTH_DATAONLY);

		//设置协议帧头
		pe_header.u16ProtolElementLength = 1;
		pe_header.tProtolElementType = eProtolElementConstant;
		pe_header.ProtolElementContent[0] = 0x5E;


		//设置协议命令字
		pe_cmder.u16ProtolElementLength = 1;
		pe_cmder.tProtolElementType = eProtolElementCommand;
		pe_cmder.ProtolElementContent[0] = 0;


		//设置协议报序号
		pe_packnum.u16ProtolElementLength = 1;
		pe_packnum.tProtolElementType = eProtolElementNormal;
		pe_packnum.ProtolElementContent[0] = 0;


		//设置协议数据部分数据
		pe_length.u16ProtolElementLength = 2;
		pe_length.tProtolElementType = eProtolElementLength;
		pe_length.ProtolElementContent[0] = 0;

		//设置协议数据状态
		pe_state.u16ProtolElementLength = 1;
		pe_state.tProtolElementType = eProtolElementNormal;
		pe_state.ProtolElementContent[0] = 0;

		//设置CRC校验字
		pe_crc.u16ProtolElementLength = 1;
		pe_crc.tProtolElementType = eProtolElementNormal;
		pe_crc.ProtolElementContent[0] = 0;
		

		//设置数据部分
		pe_data.u16ProtolElementLength = 5; //如果是定长度数据，则该字节表示数据字段长度，如果是变长度协议，则该值无效
		pe_data.tProtolElementType = eProtolElementData;
		pe_data.ProtolElementContent[0] = 0;

		AddProtolElement(pm, &pe_header);
		AddProtolElement(pm, &pe_cmder);
		AddProtolElement(pm, &pe_packnum);
		AddProtolElement(pm, &pe_length);
		AddProtolElement(pm, &pe_state);
		AddProtolElement(pm, &pe_crc);
		AddProtolElement(pm, &pe_data);

		CommandInfo cmdInfo;
		memset((void *)&cmdInfo, 0, sizeof(CommandInfo));
		cmdInfo.u32CommandNum = LOGIN_RESPONS_CMD;
		cmdInfo.tCommandCallback = LoginResponseCmdProc;
		RegistCommandInfo(pm, cmdInfo);
		
		memset((void *)&cmdInfo, 0, sizeof(CommandInfo));
		cmdInfo.u32CommandNum = UPDATE_RESPONS_CMD;
		cmdInfo.tCommandCallback = UpdateResponseCmdProc;
		RegistCommandInfo(pm, cmdInfo);
		
		return pm;
	}
	else 
	{
		return NULL;
	}
}

ProtolMachine* InitUart4Data(void)
{	
	return init_uart4data_protolset();
}

#include "usart.h"
uint8_t u8RequestBuf[512] = {0};

bool TryDeviceLogin(void)
{
	uint8_t mcuID[16] = {0};
	
	uint32_t uRanNum = 0;
	HAL_StatusTypeDef randStatus = HAL_ERROR;
	
	DeviceInfo *devInfo = GetDeviceInfo();
	LocalMachineVersion* localMach = GetAppMachineVersion();
	
	LoginRequestFrame xpLoginRequest;
	//设置协议头
	xpLoginRequest.Header.Header = FRAME_HEADER;
	xpLoginRequest.Header.CommandNum = LOGIN_REQUEST_CMD;
	xpLoginRequest.Header.PkgSerNum = 0x00;
	xpLoginRequest.Header.PckLength = GET_FRAME_LENGTH(LoginRequestFrame);
	xpLoginRequest.Header.PckStatus = randStatus;
	xpLoginRequest.Header.CrcVal = 0x01;
	//设置协议数据部分
	xpLoginRequest.Data.DevRunPos = DEV_RUN_POS_BOOT;
	memcpy(&(xpLoginRequest.Data.ModelSn), devInfo->model_sn, sizeof(devInfo->model_sn));
	memcpy(&(xpLoginRequest.Data.SoftVersion), localMach->sfv.SfVers, 3);
	memcpy(&(xpLoginRequest.Data.HardVersion), localMach->hdv.HdVers, 3);
	memcpy(&(xpLoginRequest.Data.ModelPassword), devInfo->login_password, 8);
	
//	randStatus = Get_RandomNumber(&uRanNum);
	randStatus = 0;
	xpLoginRequest.Data.MCUID.ModelRandNum = uRanNum;
	GetMCUID(xpLoginRequest.Data.MCUID.ModelMCUID);
	
	Uart4SendData((uint8_t *)&xpLoginRequest, sizeof(xpLoginRequest));
	return true;
}

//服务器回复登录请求
static int LoginResponseCmdProc(void *content, int data_length)
{
	LoginResponseFrame loginResponseFrame;
	
	if(data_length == sizeof(LoginResponseFrame))
	{
		memcpy((void *)&loginResponseFrame, content, data_length);
		
		if(loginResponseFrame.Data.DevCanWork)
			setDeviceWork(true);
		else
			setDeviceWork(false);
		
		setPackCapcity(loginResponseFrame.Data.PackCapcity);
		setPackSerialCount(loginResponseFrame.Data.PackSerialCount);
		setDevNeedUpdate(loginResponseFrame.Data.DevNeedUpdate);
		setDevMCUID(loginResponseFrame.Data.MCUID);
	
		setComServID(loginResponseFrame.Data.DevCommID);
		
		setDeviceLoginOK(loginResponseFrame.Data.DevCanWork);
	}
	else
	{
		setDeviceWork(false);
		setDeviceLoginOK(false);
	}
}

#include "UpdateData.h"
bool RequestDevicePrepareUpdate(void)
{	
	UpdateRequestFrame xpUpdateRequest;
	//设置协议头
	xpUpdateRequest.Header.Header = FRAME_HEADER;
	xpUpdateRequest.Header.CommandNum = UPDATE_REQUEST_CMD;
	xpUpdateRequest.Header.PkgSerNum = 0x00;
	xpUpdateRequest.Header.PckLength = GET_FRAME_LENGTH(UpdateRequestFrame);
	xpUpdateRequest.Header.PckStatus = 0;
	xpUpdateRequest.Header.CrcVal = 0x01;
	
	//在bootloader中发送ePrepareUpdate，服务器会查找升级文件
	//然后打开升级，打开成功之后会通知设备进一步请求数据
	//和CAN升级的后续相同
	xpUpdateRequest.Data.DeviceID = getComServID();
	xpUpdateRequest.Data.UpdateSubCmd = ePrepareUpdate;
	
	xpUpdateRequest.Data.UpdateData[0] = 0xFF;
	xpUpdateRequest.Data.UpdateData[1] = 0xFF;

	Uart4SendData((uint8_t *)&xpUpdateRequest, sizeof(xpUpdateRequest));
	return true;
}

static uint8_t updateResponseDataBuf[512] = {0x0};
bool u8ServerResponse = false;

static int UpdateResponseCmdProc(void *content, int data_length)
{
	uint32_t response_length = 0;
	
	UpdateResponseFrame *updateResponseFrame = xp_malloc(data_length);
	
	memcpy(updateResponseFrame, content, data_length);
	
	uint8_t u8SubCmd = updateResponseFrame->Data.UpdateSubCmd;
	
	SvrCmdResponseProc(u8SubCmd, updateResponseFrame->Data.UpdateData, GET_DATA_LENGTH(data_length), 
											updateResponseDataBuf, &response_length);
	
	
	if(response_length <= 0)
	{
		xp_free(updateResponseFrame);
		return 0;
	}
	
	UpdateRequestFrame updateRequestFrame;
	//设置协议头
	updateRequestFrame.Header.Header = FRAME_HEADER;
	updateRequestFrame.Header.CommandNum = UPDATE_REQUEST_CMD;
	updateRequestFrame.Header.PkgSerNum = 0x00;
	updateRequestFrame.Header.PckLength = GET_FRAME_LENGTH(UpdateRequestFrame);
	updateRequestFrame.Header.PckStatus = 0;
	updateRequestFrame.Header.CrcVal = 0x01;
	
	//在bootloader中发送ePrepareUpdate，服务器会查找升级文件
	//然后打开升级，打开成功之后会通知设备进一步请求数据
	//和CAN升级的后续相同
	updateRequestFrame.Data.DeviceID = getComServID();
	updateRequestFrame.Data.UpdateSubCmd = updateResponseDataBuf[0];
	memcpy(&(updateRequestFrame.Data.UpdateData), updateResponseDataBuf + 1, response_length - 1);
	
	Uart4SendData((uint8_t *)&updateRequestFrame, sizeof(updateRequestFrame));

	xp_free(updateResponseFrame);
	u8ServerResponse = true;
	return 0;
}
